///////////////////////////////////////////////////////////////////////////////
/// Copyright (c) 2013, 10wmj.com
/// All rights reserved.
///
/// @file		MatchConnection.cpp
/// @brief		
///
/// @version	1.0
/// @author		liangX
/// @date		2013.10.08
///
///////////////////////////////////////////////////////////////////////////////

#include "ActiveConnsList.h"
#include "GameMemoryPool.h"
#include "TLog.h"
#include "Config.h"
#include "CsvDataMgr.h"
#include "StreamPacketBuilder.h"
#include "CBrcMsgHandle.h"


using namespace std;

ActiveConnsList::ActiveConnsList():
	m_checked(false)
{
	m_cur_hour_ = 255;

	m_last_broast_time = 0;
	m_last_check_robot_gold_time = 0;
}

ActiveConnsList::~ActiveConnsList()
{
	clear();
}



FrontClientHandler * ActiveConnsList::find(int uid)
{
	MAP_CON_ITOR it = m_clients.find( uid );
	if ( it != m_clients.end() )
	{
		return it->second ;
	}
	return NULL;
	
}


bool ActiveConnsList::add( FrontClientHandler * info)
{
	MAP_CON_REUSLT ret = m_clients.insert( MAP_CON_VALUE( info->getClientId() , info ));
	return ret.second;
}

bool ActiveConnsList::remove(int uid)
{
	MAP_CON_ITOR it = m_clients.find( uid );
	if ( it != m_clients.end() )
	{
		m_clients.erase( it );
		return true ;
	}
	return false  ;
}


void ActiveConnsList::clear()
{
	m_clients.clear();
}


bool ActiveConnsList::release( FrontClientHandler * handler  )
{
	bool ok  = false ;
	MAP_CON_ITOR it = m_clients.find( handler->getClientId() );
	if ( it != m_clients.end() )
	{
		FrontClientHandler * p  = it->second;
		m_clients.erase( it );
		ok  = true ;
	}
	WL(LL_DEV,"player = %d close release\n",handler->getClientId() );
	safeReleaseHandler( handler );
	return ok  ;
}

void ActiveConnsList::broadcast( u8_t * data , int len , int uid )
{
	MAP_CON_ITOR it = m_clients.begin();
	for ( ; it != m_clients.end() ; it++)
	{
		FrontClientHandler * p  = it->second;
		Player * player = p->getPlayer() ;
		if ( p &&  player && player->get_user_id() != uid && player->isNormalPlayer() )
		{	
			p->safeSend( data , len );
		}
	}
}

//根据房间id发送消息
void ActiveConnsList::sendroomdata(u16_t cmd, u8_t * data , int len, int roomid , DWORD uid)
{
	MAP_CON_ITOR it = m_clients.begin();
	for ( ; it != m_clients.end() ; it++)
	{
		FrontClientHandler * p  = it->second;
		if(!p)
		{
			continue;
		}
		Player * player = p->getPlayer() ;
		if ( p &&  player && player->isNormalPlayer() && (player->GetCurRoomID() == roomid))
		{	
			if(uid > 0 && uid == player->get_user_id())
			{
				continue;
			}
			p->sendPacket(cmd,  data , len );
		}
	}
}

void ActiveConnsList::brcSvrDataRestore(DWORD roomid)
{	
	MAP_CON_ITOR it = m_clients.begin();
	for ( ; it != m_clients.end() ; it++)
	{
		FrontClientHandler * p  = it->second;
		if(!p)
		{
			continue;
		}
		Player * player = p->getPlayer() ;
		if ( p &&  player && player->isNormalPlayer() && (player->GetCurRoomID() == roomid))
		{
			if(player->getTable())
			{
				BRCTable *pTable = (BRCTable*)(player->getTable());
				if(pTable)
				{
					pTable->recoverJoinTableAfterBrcRestart(player);
				}
			}
		}
	}
}

//10秒一次
void ActiveConnsList::update()
{
	MAP_CON_ITOR it = m_clients.begin();
	time_t curtime = time(NULL);
	if (m_last_check_robot_gold_time <= 0)
		m_last_check_robot_gold_time = curtime;

		// 1个小时检查一次机器人的金币数
	bool check_robot_gold = false;
	if (curtime - m_last_check_robot_gold_time > 3600)
	{		
		m_last_check_robot_gold_time = curtime;
		check_robot_gold = true;
	}	
	
	for ( ; it != m_clients.end() ; )
	{
		FrontClientHandler * p  = it->second;
		//printf("zq player = %d, socketid = %d activetime = %d\n",p->getClientId(), p->get_handle(), p->getActiveTime() );
		if ( p->isClosed() || p->isTimeout( Config::instance()->m_timeouts.off_line_timeout ))
		{
			p->close(); //把socket关了
			//printf("zq player = %d, socketid = %d isTimeout close 22 \n",p->getClientId(), p->get_handle() );
			if ( !p->enableRelease() ) //不允许释放,放到关闭列表
			{
				WL(LL_INFO,"active update nUserID:%d  table addr:0x%02x  table_id:%d \n", p->getClientId(), p->getPlayer()->getTable(), p->getPlayer()->get_table_id());
				m_clients.erase( it++ );
				CloseConnsList::instance()->add( p );
			}
			else
			{
				safeReleaseHandler( p );
				m_clients.erase( it++ );
			}
			continue;
		}


		if (check_robot_gold)
		{		
			Player *player = p->getPlayer();
			
			if ( (player) && (!player->isNormalPlayer()))
			{
				player->check_robot_gold();
				// INT64 gold = player->get_user_gold();
				// if (gold < 2000)
				// {
				// 	player->add_user_gold(40000);

				// 	SQLReq * req = SQLMemoryPool::instance()->mallocReq( REQ_TYPE_DDL,this );
				// 	snprintf( req->sql , sizeof(req->sql),"call p_rechange_gold(%u,%lld,%d)",player->get_user_id(),player->get_user_score()->gold , 40000);
				// 	player->add_user_gold( 40000 );
				// 	DataBaseCommitThread::instance()->push( req ) ;
				// }
			}
		}

		//在桌子里面的用户10分钟不玩游戏则T出桌子
		if ( (p->getPlayer()) && (p->getPlayer()->isNormalPlayer()) && (p->getPlayer()->getTable()) )
		{
			//printf( "zq curtime = %d p->getPlayer()->getNoPlayTime() = %d  p->getPlayer()->getTable() = %x\r\n", curtime, p->getPlayer()->getNoPlayTime(), p->getPlayer()->getTable() );
			if ( curtime - p->getPlayer()->getNoPlayTime() >= 600 )
			{
				p->getPlayer()->getTable()->SystemKickPlayer( p->getPlayer() );
			}
		}
		//上次在桌子这次不在桌子
		if( (p->getPlayer()->m_last_tableid > INVALID_TABLE) && (p->getPlayer()->get_table_id() == INVALID_TABLE) )
		{
			//退出桌子
			p->getPlayer()->NotifyStatusToFriend( 1 );
		}
		else if( (p->getPlayer()->m_last_tableid == INVALID_TABLE) && (p->getPlayer()->get_table_id() > INVALID_TABLE) )
		{
			//进入桌子
			p->getPlayer()->NotifyStatusToFriend( 1 );
		}

		else if( (p->getPlayer()->m_last_tableid > INVALID_TABLE) && (p->getPlayer()->get_table_id() > INVALID_TABLE) &&  (p->getPlayer()->m_last_tableid/10000) != (p->getPlayer()->get_table_id()/10000))
		{
			p->getPlayer()->NotifyStatusToFriend( 1 );
		}
		
		p->getPlayer()->m_last_tableid = p->getPlayer()->get_table_id();
		p->ClearLastDayVar();
		it++;
	}

	
	tm *ptrtm = localtime(&curtime);
	if (ptrtm == NULL)
		return;

	int curhour = ptrtm->tm_hour;
	int curminute = ptrtm->tm_min;
	int cursecond = ptrtm->tm_sec;
	if (m_last_broast_time <= 0)
		m_last_broast_time = curtime;

	if (curtime - m_last_broast_time > 60) {
		m_last_broast_time = curtime;

		int ram_num = rand()%100;

		
		if (ram_num > 65) {
			std::string chartmsg = CsvDataMgr::instance()->GetRandomManChatMsg(ptrtm->tm_wday);
			if (chartmsg.length() > 1) {
				std::string namemsg = CsvDataMgr::instance()->GetRandomManName();
				StreamPacketBuilder::instance()->notifyBroadcastByCsv(namemsg, chartmsg);
			}
		}
		else if (ram_num > 10) {
			std::string chartmsg = CsvDataMgr::instance()->GetRandomWomanChatMsg(ptrtm->tm_wday);
			if (chartmsg.length() > 1) {
				std::string namemsg = CsvDataMgr::instance()->GetRandomWomanName();
				StreamPacketBuilder::instance()->notifyBroadcastByCsv(namemsg, chartmsg);
			}
		}
	}
}

void ActiveConnsList::OnHourBegin(int curhour)
{
}

int ActiveConnsList::GetRoomID(DWORD playerid)
{
	FrontClientHandler * pHandle = find(playerid);
	if (pHandle == NULL)
		return 0;

	Player * pPlayer = pHandle->getPlayer();
	if (pPlayer == NULL)
		return 0;

	return pPlayer->get_table_id();
}

void ActiveConnsList::safeReleaseHandler( FrontClientHandler * handler )
{
	if ( handler->getPlayer() )
	{
		WL(LL_DEV,"ActiveConnsList::safeReleaseHandler emptyPlayer player:%d addr:0x%02x \n" , handler->getPlayer()->get_user_id(), handler->getPlayer());
		GameMemoryPool::instance()->freePlayerClass( handler->getPlayer() );
		//WL(LL_DEV,"ActiveConnsList::safeReleaseHandler emptyPlayer \n" );
		handler->emptyPlayer();
	}
	handler->get_event_scheduler()->free_event_object( handler );
}

CloseConnsList::CloseConnsList():
m_checked(false)
{

}

CloseConnsList::~CloseConnsList()
{
	clear();
}



FrontClientHandler * CloseConnsList::find(int uid)
{
	MAP_CON_ITOR it = m_clients.find( uid );
	if ( it != m_clients.end() )
	{
		return it->second ;
	}
	return NULL;

}


bool CloseConnsList::add( FrontClientHandler * info)
{
	MAP_CON_ITOR it = m_clients.find( info->getClientId() );
	if ( it != m_clients.end() )
	{
		FrontClientHandler * p  = it->second;
		if ( p->getPlayer() && p->getPlayer()->getTable() )
		{
			p->getPlayer()->getTable()->leaveTable( p->getPlayer() ); 
		}
		safeReleaseHandler( p ); 
		m_clients.erase( it );
	}
	MAP_CON_REUSLT ret = m_clients.insert( MAP_CON_VALUE( info->getClientId() , info ));
	return ret.second;
}

bool CloseConnsList::remove(int uid)
{
	MAP_CON_ITOR it = m_clients.find( uid );
	if ( it != m_clients.end() )
	{
		m_clients.erase( it );
		return true ;
	}
	return false  ;
}


void CloseConnsList::clear()
{
	m_clients.clear();
}


bool CloseConnsList::release( FrontClientHandler * handler )
{
	if ( handler == NULL ) return false ;
	bool ok  = false ;
	MAP_CON_ITOR it = m_clients.find( handler->getClientId() );
	if ( it != m_clients.end() )
	{
		FrontClientHandler * p  = it->second;
		m_clients.erase( it );
		ok  = true ;
	}
	WL(LL_DEV,"player = %d close release\n",handler->getClientId() );
	safeReleaseHandler( handler );
	return ok  ;
}

void CloseConnsList::brcSvrDataRestore(DWORD roomid)
{
	MAP_CON_ITOR it = m_clients.begin();
	for ( ; it != m_clients.end() ; it++)
	{
		FrontClientHandler * p  = it->second;
		Player * player = p->getPlayer() ;
		if ( p &&  player && player->isNormalPlayer() && (player->GetCurRoomID() == roomid))
		{
			if(player->getTable())
			{
				BRCTable *pTable = (BRCTable*)(player->getTable());
				if(pTable)
				{
					pTable->DeleteUserAttr(player);
	
				}		
			}
		}
	}
}

void CloseConnsList::update()
{
	MAP_CON_ITOR it = m_clients.begin();
	DWORD curtime = time(NULL);
	for ( ; it != m_clients.end() ;)
	{
		FrontClientHandler * p  = it->second;
		if ( time(NULL) -  p->getActiveTime() >= 60 )
		{
			WL(LL_INFO," CloseConnsList player = %d, socketid = %d activetime = %d\n",p->getClientId(), p->get_handle(), p->getActiveTime());
			if ( !p->enableRelease() ) //不允许释放,先离开桌子
			{
				if ( p->getPlayer() && p->getPlayer()->getTable() )
				{
					WL(LL_INFO,"close update nUserID:%d  table addr:0x%02x  table_id:%d \n", p->getClientId(), p->getPlayer()->getTable(), p->getPlayer()->get_table_id());
					//printf("close update nUserID:%d  table addr:0x%02x  table_id:%d \n", p->getClientId(), p->getPlayer()->getTable(), p->getPlayer()->get_table_id());
					p->getPlayer()->getTable()->leaveTable( p->getPlayer() ); 
				}
				
			}
			//用户离线
			if ( p->getPlayer() )
			{
				p->getPlayer()->NotifyStatusToFriend( 0 );
			}
			safeReleaseHandler( p );
			m_clients.erase( it++ );
			continue;
		}
		it++;
	}
}

void CloseConnsList::safeReleaseHandler( FrontClientHandler * handler )
{
	if ( handler == NULL ) return  ;
	if ( handler->getPlayer() )
	{
		WL(LL_DEV,"CloseConnsList::safeReleaseHandler emptyPlayer player:%d addr:0x%02x \n" , handler->getPlayer()->get_user_id(), handler->getPlayer());
		//printf("CloseConnsList::safeReleaseHandler emptyPlayer player:%d addr:0x%02x \n" , handler->getPlayer()->get_user_id(), handler->getPlayer());;
		GameMemoryPool::instance()->freePlayerClass( handler->getPlayer() );
		handler->emptyPlayer();
	}
	handler->get_event_scheduler()->free_event_object( handler );
}

